<?php

namespace services;

require_once ROOT_LIBRARY . DS . 'utils.php';

class delivery_promises {

    const RULE_RESULT_TYPE_AMOUNT_OF_TIME = 2;
    const RULE_RESULT_TYPE_SET_TIME = 1;

    private $_cache;
    private $_oms;
    private $_rule_model;
    private $_location_model;

    function __construct($cache, $oms, $location_model, $rule_model) {
        $this->_cache = $cache;
        $this->_oms = $oms;
        $this->_rule_model = $rule_model;
        $this->_location_model = $location_model;
    }

    public function process_rules($sku, $location, $date) {
            $rules = $this->_rule_model->get_all();
            $stock = $this->_oms->get_stock($sku);
            
            $time = 0;
            $type = self::RULE_RESULT_TYPE_AMOUNT_OF_TIME;

            foreach ($rules as $rule) {
                if ($this->check_condition($stock, $location, $date, $rule)) {
                    \utils::log("$sku & $location (STOCK = $stock) -> " . $rule['comment'] ."(". $rule['conditions'] .")" );
                    $res = $this->evaluate($location, $rule);
                    if ($res['result_type'] == self::RULE_RESULT_TYPE_AMOUNT_OF_TIME)
                        $time += $res['result'];
                    else if ($res['result_type'] == self::RULE_RESULT_TYPE_SET_TIME) {
                        $time = $res['result'];
                        $type = self::RULE_RESULT_TYPE_SET_TIME;
                        break;
                    }
                }
            }

            $result = array('result_type' => $type, 'result' => $time);
            return $result;            
    }

    public function check_condition($stock, $location, $date, $rule) {

        if ($rule['conditions'] == null)
            return true;
        $arr_conditions = json_decode($rule['conditions'], true);
        $result = true;

        foreach ($arr_conditions as $condition) {
            switch ($condition['type']) {
                case "RULE_CONDITION_STOCK":
                    $result = $result && \utils::invokeOperator($stock, $condition['operator'], $condition['params']);
                    break;
                case "RULE_CONDITION_LOCATION":
                    $result = $result && \utils::invokeOperator($location, $condition['operator'], $condition['params']);
                    break;
                case "RULE_CONDITION_DATE":
                    $result = $result && \utils::invokeDateOperator($date, $condition['operator'], $condition['params']);
                    break;
            }
        }

        return $result;
    }

    public function evaluate($location, $rule) {

        $action = json_decode($rule['action']);
        $time = 0;
        $type = self::RULE_RESULT_TYPE_AMOUNT_OF_TIME;
        switch ($action->type) {
            case 'RULE_ACTION_GET_LOCATION_TIME':
                $time = $this->_location_model->get_province_time($location);
                break;
            case 'RULE_ACTION_GET_SUPLIER_LEAD_TIME':
            case 'RULE_ACTION_SET_TIME':
                $time = $action->value;
                break;
            case 'RULE_ACTION_SET_TARGET_TIME':
                $time = $action->value;
                $type = self::RULE_RESULT_TYPE_SET_TIME;
                break;
        }

        return array('result_type' => $type, 'result' => $time);
    }

    public function get_time($sku, $location, $date) {

        $time = $this->_cache->cache('shipping_time_' . $sku . "_" . $location);
        if ($time)
            return $time;

        $time = $this->process_rules($sku, $location, $date);
        $this->_cache->cache('shipping_time_' . $sku . "_" . $location, $time);
        return $time;
    }

    public function get_time_all_location($sku, $date) {

        $results = $this->_cache->cache('st_all_location_' . $sku);
        if ($results)
            return $results;

        $results = array();
        $locations = $this->_location_model->get_all();
        foreach ($locations as $location) {
            $results[$location['name']] = $this->get_time($sku, $location['name'], $date);
        }
        $this->_cache->cache('st_all_location_' . $sku, $results);
        return $results;
    }

}

?>
